package com.gsocket.sever;

import com.gsocket.event.sever.ConnectListener;
import com.gsocket.event.sever.ReceiveListener;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.net.Socket;

public class Connection implements Runnable {


    private Socket socket;
    private GSocketSever gSocketSever;
    private boolean isRunning;
    private ConnectListener connectListener;
    private ReceiveListener receiveListener;

    public Socket getSocket() {
        return socket;
    }

    public boolean isRunning() {
        return isRunning;
    }

    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();
            byte[] buffer = new byte[10240];
            int ch;
            while (isRunning && (ch = is.read(buffer)) != -1) {
                if (socket.isClosed()) {
                    close();
                    break;
                }
                ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
                bytestream.write(buffer, 0, ch);
                byte[] data = bytestream.toByteArray();
                bytestream.close();
                if (receiveListener != null) {
                    receiveListener.onReceived(this, data);
                }
            }
            close();
        } catch (IOException e) {
            e.printStackTrace();
            close();
        }
    }


    Connection(Socket socket, GSocketSever gSocketSever) {
        this.socket = socket;
        this.gSocketSever = gSocketSever;
        try {
            connectListener = gSocketSever.getConnectListenerClss() == null ? gSocketSever.getConnectListener() : (ConnectListener) gSocketSever.getConnectListenerClss().getDeclaredConstructor().newInstance();
            receiveListener = gSocketSever.getReceiveListenerClss() == null ? gSocketSever.getReceiveListener() : (ReceiveListener) gSocketSever.getReceiveListenerClss().getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }
        isRunning = true;
        if (connectListener != null) {
            connectListener.onConnect(this);
        }
    }

    public void send(byte[] message) {
        PrintStream ps;
        try {
            ps = new PrintStream(socket.getOutputStream(), true);
            ps.write(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void close() {
        isRunning = false;
        try {
            if (!socket.isClosed()) {
                socket.shutdownOutput();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (connectListener != null) {
            connectListener.onClosed(this);
        }
    }
}
